﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>


		//操作符---第一节

////原码、反码、补码
//int main()
//{
//	int a = 10;
//	//正数的原码、反码、补码相同
//	// 
//	//00000000000000000000000000001010  -原码
//	//00000000000000000000000000001010  -反码
//	//00000000000000000000000000001010  -补码
//	int b = -10;
//
//	//10000000000000000000000000001010  -原码
//	//11111111111111111111111111110101  -反码
//	//11111111111111111111111111110110  -补码
//	
//	//00000000000000000000000000001010  -a补码
//	//11111111111111111111111111110110  -b补码
//	// 
//	//两数相加，使用补码相加，整数有32个bit位数，超过即舍去
//
//	return 0;
//}


////移位操作符
//int main()
//{
//	int a = 12;
//	int b = a << 1;		//即扩大2^1倍
//	//左移操作符
//	//二进制数左移一位，左边抛弃，右边补0
//
//	//00000000000000000000000000001100  a的补码
//	//00000000000000000000000000011000  b的补码 8 + 16 = 24
//
//	int c = -12;
//	int d = c >> 1;		//即缩小2^1倍
//	//右移操作符
//	//(算术右移)	左边用原来的符号位填充，右边丢弃
//	//(逻辑右移) 左边用0填充，右边丢弃
//
//	//00000000000000000000000000001100  c的原码
//	//11111111111111111111111111110011  c的反码
//	//11111111111111111111111111110100  c的补码
//	//11111111111111111111111111111010  d的补码
//	//10000000000000000000000000000101  d的反码
//	//10000000000000000000000000000110  d的原码   -(4+2) = -6
//
//	printf("a=% d, b=% d\n", a, b);
//	printf("a=% d, b=% d\n", c, d);
//	
//	return 0;
//}



// & 按位与			&& 逻辑与
// | 按位或			|| 逻辑或			


// & 按位与		对应二进制位，有0则为0，两个同时1才为1	
// | 按位或		对应二进制为，有1则为1，两个同时为0才是0	
// ^ 按位异或		对应二进制为，相同为0，相异为1
// ~ 按位取反		1变0，0变1

//int main()
//{
//	int a = -7;
//	int b = 4;
//	//10000000000000000000000000000111  a的原码
//	//11111111111111111111111111111000  a的反码
//	
//	//11111111111111111111111111111001  a的补码
//	//00000000000000000000000000000100  b的补码
//
//	int c = a & b;
//	//11111111111111111111111111111001  a的补码
//	//00000000000000000000000000000100  b的补码
//	//00000000000000000000000000000000  a&b = 0
//
//	int d = a | b;
//	//11111111111111111111111111111001  a的补码
//	//00000000000000000000000000000100  b的补码
//	//11111111111111111111111111111101  a|b的补码
//	//10000000000000000000000000000010
//	//10000000000000000000000000000011  a|b的原码 = -(2+1) = -3
//
//	int e = a ^ b;
//	//11111111111111111111111111111001  a的补码
//	//00000000000000000000000000000100  b的补码
//	//11111111111111111111111111111101  a^b的补码
//	//10000000000000000000000000000010
//	//10000000000000000000000000000011  a^b的原码 = -(2+1) = -3
//
//
//	int f = ~a;
//	//11111111111111111111111111111001  a的补码
//	//00000000000000000000000000000110  ~a的补码
//	//00000000000000000000000000000110  ~a的反码
//	//00000000000000000000000000000110  ~a的原码
//		
//
//	printf("c = %d\n",c);
//	printf("d = %d\n",d);
//	printf("e = %d\n",e);
//	printf("f = %d\n",f);
//	return 0;
//}


//练习
// 一、交换两个数

//① 设置临时变量
//int main()
//{
//	int a = -3;
//	int b = 8;
//	int temp = 0;
//	printf("交换前a=%d,b=%d\n", a, b);
//
//	temp = a;
//	a = b;
//	b = temp;
//
//	printf("交换后a=%d,b=%d\n", a, b);
//	
//	return 0;
//}

////② 不设置临时变量 相加（缺点：数太大会造成溢出的情况）
//int main()
//{
//	int a = -3;
//	int b = 8;
//	printf("交换前a=%d,b=%d\n", a, b);
//	a = a + b;
//	b = a - b;
//	a = a - b;
//	printf("交换后a=%d,b=%d\n", a, b);
//	return 0;
//}

////③ 使用位操作符
//int main()
//{
//	int a = -3;
//	int b = 8;
//	printf("交换前a=%d,b=%d\n", a, b);
//	//a ^ a = 0		
//	//a ^ 0 = a
//	a = a ^ b;
//	b = a ^ b;  // a^a^b
//	a = a ^ b;	
//	printf("交换后a=%d,b=%d\n", a, b);
//	return 0;
//}



//二、编写代码实现：求⼀个整数存储在内存中的⼆进制中1的个数

////解法1.使用%2，/2的方式求1的个数
//int main()
//{
//	unsigned int n = 0;
//	int count = 0;
//	scanf("%d", &n);
//	while (n)
//	{
//		if (n % 2 == 1)//也可以写成直接写成if(n%2)
//			count++;
//		n /= 2;
//	}
//	printf("该数二进制数中1的个数有%d个\n",count);
//	return 0;
//}

//解法2.使用1与n按位与，若为1，则相加
//
////int count_one_bit1(int m)
////{
////	int count = 0;
////	for (int i = 0; i < 32; i++)
////	{
////		if ((m >> i) & 1 == 1)
////		{
////			count++;
////		}
////	}
////	return count;
////}
////
//
//
//int count_one_bit2(int n)
//{
//	int count = 0;
//	while (n)
//	{
//		count++;
//		n = n & (n - 1);
//
//	}
//	return count;
//}
//
//int main()
//{
//	int n = 0;
//
//	scanf("%d", &n);
//
//	//int count = count_one_bit1(n);
//	int count = count_one_bit2(n);
//
//	printf("%d", count);
//
//	return 0;
//}


////三、⼆进制位置0或者置1
////编写代码将13⼆进制序列的第5位修改为1，然后再改回0
//int main()
//{
//	int a = 13;
//	a = a | 1 << (5 - 1);
//	printf("将二进制第五位改为1后变为%d\n", a);
//	a = a & ~(1 << 4);
//	printf("将二进制第五位改回来后变为%d\n", a);
//	return 0;
//}




		//操作符第二节


 //逗号表达式，从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。

//int main()
//{
//	int a = 1;
//	int b = 2;
//	int c = (a > b, a = b + 10, a, b = a + 1);//逗号表达式
//			//0，  a=2+10=12,   12,b = 12+1=13
//	printf("%d",c);
//
//}	


//操作数和操作符

//void text()
//{
//	printf("haha\n");
//}
//
//int Add(int a, int b)
//{
//	return a + b;
//}
////函数在调用的时候，函数名后面的括号就是函数调用操作符
////() - 操作数：函数名，参数
//int main()
//{
//	text();
//	int c = Add(1, 2);
//	printf("%d\n", c);
//
//	return 0;
//}


 //结构体

//学生的基本信息
//姓名，性别，年龄，学号


//结构体的声明和定义
struct student
{
	char name[20];	//姓名
	char gender[20];//性别
	int age;		//年龄
	char id[20];	//学号

}s3;//这里也可以定义结构体，但这里定义是全局变量

struct Print
{
	int x;
	int y;
};

struct Node
{
	int data;
	struct Print p;
	struct Node* next;

};

void str_print(struct student s)
{

	printf("%s %s %d %s\n", s.name, s.gender, s.age, s.id);

}


int main()
{
	struct student s1 = { "张三","男",20,"20230101" };	//这里是局部变量
	struct student s2 = { .age = 21,.name = "李四",.gender = "女",.id = "20220101"};
	struct Node n1 = { 100,{4,5},NULL };

	printf("%s %s %d %s\n", s1.name, s1.gender, s1.age, s1.id);
	//printf("%s %s %d %s\n", s2.name, s2.gender, s2.age, s2.id);
	str_print(s2);
	str_print(s3);



	return 0;
}